package com.base.self.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.poi.excel.BigExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.base.mapper.voipmapper.SubscribersMapper;
import com.base.po.voip.Subscribers;
import com.base.po.voip.Users;
import com.base.result.PageUtils;
import com.base.result.ResponseResult;
import com.base.result.ResponseResultUtils;
import com.base.self.common.SelfRuntimeException;
import com.base.self.dto.selfOrder.*;
import com.base.self.entity.*;
import com.base.self.mapper.*;
import com.base.self.service.ISelfOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;

/**
 * <p>
 * 商品订单 服务实现类
 * </p>
 *
 * @author XiFYuW
 * @since 2020-11-18
 */
@Service
public class SelfOrderServiceImpl extends ServiceImpl<SelfOrderMapper, SelfOrder> implements ISelfOrderService {

    private final SelfOrderMapper selfOrderMapper;

    private final CommodityMapper commodityMapper;

    private final PayDealMapper payDealMapper;

    private final BroadcastMapper broadcastMapper;

    private final SubscribersMapper subscribersMapper;

    private final PtintegralMapper ptintegralMapper;

    private final SelfDeliverMapper selfDeliverMapper;

    public SelfOrderServiceImpl(SelfOrderMapper selfOrderMapper,
                                CommodityMapper commodityMapper,
                                PayDealMapper payDealMapper,
                                BroadcastMapper broadcastMapper,
                                SubscribersMapper subscribersMapper,
                                PtintegralMapper ptintegralMapper,
                                SelfDeliverMapper selfDeliverMapper) {
        this.selfOrderMapper = selfOrderMapper;
        this.commodityMapper = commodityMapper;
        this.payDealMapper = payDealMapper;
        this.broadcastMapper = broadcastMapper;
        this.subscribersMapper = subscribersMapper;
        this.ptintegralMapper = ptintegralMapper;
        this.selfDeliverMapper = selfDeliverMapper;
    }


    @Override
    public ResponseResult selfOrderWebList(SelfOrderWebListDTO selfOrderWebListDTO) {
        String orderNo = selfOrderWebListDTO.getOrderNo();
        String mobile = selfOrderWebListDTO.getMobile();
        Integer status = selfOrderWebListDTO.getStatus();
        String recipientsName = selfOrderWebListDTO.getRecipientsName();
        final Map<String, Object> data = PageUtils.getDateMap(() -> page(PageUtils.getPage(
                new Page<>(), selfOrderWebListDTO.getOffset(), selfOrderWebListDTO.getLimit()),
                new LambdaQueryWrapper<SelfOrder>()
                        .eq(!StringUtils.isEmpty(orderNo), SelfOrder::getOrderNo, orderNo)
                        .eq(!StringUtils.isEmpty(mobile), SelfOrder::getMobile, mobile)
                        .eq(status != null && status > 0, SelfOrder::getStatus, status)
                        .like(!StringUtils.isEmpty(recipientsName), SelfOrder::getRecipientsName, recipientsName)
                        .eq(SelfOrder::getIsDel, 0)
                        .orderByDesc(SelfOrder::getSuccessTime)));
        return ResponseResultUtils.getResponseResultS("查询成功", data);
    }

    @Override
    public ResponseResult deliverOrder(DeliverOrderDTO deliverOrderDTO) {
        final SelfOrder selfOrder = selfOrderMapper.selectById(deliverOrderDTO.getId());
        Optional.ofNullable(selfOrder).orElseThrow(() -> new SelfRuntimeException(ResponseResultUtils.getResponseResultF("订单不存在")));
        if (selfOrder.getExpressStatus() != 0) {
            return ResponseResultUtils.getResponseResultF("订单已发货");
        }
        if (selfOrder.getStatus() == 1) {
            return ResponseResultUtils.getResponseResultF("订单未支付");
        }
        if (selfOrder.getStatus() == 4) {
            return ResponseResultUtils.getResponseResultF("订单已收货");
        }
        if (selfOrder.getStatus() == 5) {
            return ResponseResultUtils.getResponseResultF("订单已取消");
        }
        if (selfOrder.getStatus() == 6) {
            return ResponseResultUtils.getResponseResultF("订单拼团中");
        }
        if (selfOrder.getRefundStatus() == 1) {
            return ResponseResultUtils.getResponseResultF("订单已申请退款");
        }
        Date date = DateUtil.date();
        selfOrder.setExpressNumber(deliverOrderDTO.getExpressNumber());
        selfOrder.setExpressOrder(deliverOrderDTO.getExpressOrder());
        selfOrder.setExpressStatus(1);
        selfOrder.setStatus(3);
        selfOrder.setUpdateTime(date);
        selfOrderMapper.updateById(selfOrder);

        /*商品订单发货信息 ==> 自动确认收货*/
        final SelfDeliver selfDeliver1 = selfDeliverMapper.selectOne(new LambdaQueryWrapper<SelfDeliver>().eq(SelfDeliver::getOrderId, selfOrder.getId()));
        if (selfDeliver1 == null) {
            final SelfDeliver selfDeliver = SelfDeliver
                    .builder()
                    .createTime(date)
                    .expirationTime(DateUtil.offsetDay(date, 7))
                    .orderId(selfOrder.getId())
                    .isPerform(0)
                    .isDel(0)
                    .build();
            selfDeliverMapper.insert(selfDeliver);
        }
        return ResponseResultUtils.getResponseResultS("发货成功");
    }

    @Override
    public void selfOrderExport(HttpServletResponse response, SelfOrderExportDTO selfOrderExportDTO) throws IOException {
        String[] str = split(selfOrderExportDTO.getCreateTime());
        List<SelfOrder> data = selfOrderMapper.selectList(new LambdaQueryWrapper<SelfOrder>()
                .between(str.length > 0, SelfOrder::getCreateTime, str[0], str[1])
        );
        List<Map<String, Object>> list = new ArrayList<>();
        for (SelfOrder selfOrder : data) {
            final Commodity commodity = commodityMapper.selectById(selfOrder.getCommodityId());
            final PayDeal payDeal = payDealMapper.selectOne(new LambdaQueryWrapper<PayDeal>()
                    .eq(PayDeal::getOrderNo, selfOrder.getOrderNo()));
            Map<String, Object> itemX = new LinkedHashMap<>();
            itemX.put("订单ID", selfOrder.getId());
            itemX.put("商户订单编号", selfOrder.getOrderNo());
            itemX.put("创建时间", DateUtil.format(selfOrder.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
            itemX.put("手机号", selfOrder.getMobile());
            itemX.put("数量", selfOrder.getNumber());
            itemX.put("订单状态", tradeStatus(selfOrder.getStatus()));
            itemX.put("订单实付价", selfOrder.getRealPrice());
            itemX.put("订单折扣价", selfOrder.getDiscountPrice());
            itemX.put("订单支付方式", payWayStatus(selfOrder.getPayWay()));
            itemX.put("订单支付时间", DateUtil.format(selfOrder.getPayTime(), "yyyy-MM-dd HH:mm:ss"));
            itemX.put("订单交易流水号", payDeal != null ? payDeal.getPayDealNo() : "");
            itemX.put("商品名称", commodity.getCommodityName());
            itemX.put("商品实付价", commodity.getCommodityRealPrice());
            itemX.put("商品市场价", commodity.getCommodityMarketPrice());
            itemX.put("商品分区", commoditySubarea(commodity.getCommoditySubarea()));
            itemX.put("收件人手机号", selfOrder.getRecipientsMobile());
            itemX.put("收件人姓名", selfOrder.getRecipientsName());
            itemX.put("收件人地址", selfOrder.getRecipientsAddress());
            itemX.put("快递单号", selfOrder.getExpressOrder());
            itemX.put("快递状态", getExpressStatus(selfOrder.getExpressStatus()));
            itemX.put("快递公司编号", selfOrder.getExpressNumber());
            itemX.put("是否置换", isReplacementStatus(selfOrder.getIsReplacement()));
            itemX.put("备注", selfOrder.getRemark());
            list.add(itemX);
        }

        String tempPath = System.getProperty("java.io.tmpdir") + IdUtil.fastSimpleUUID() + ".xlsx";
        File file = new File(tempPath);
        BigExcelWriter bigExcelWriter = ExcelUtil.getBigWriter(file);
        bigExcelWriter.write(list, true);
        response.setHeader("Content-Disposition","attachment;filename="
                + URLEncoder.encode("订单信息表(" + selfOrderExportDTO.getCreateTime() + ").xlsx", "UTF-8"));
        ServletOutputStream out = response.getOutputStream();
        file.deleteOnExit();
        bigExcelWriter.flush(out, true);
        IoUtil.close(out);
    }

    @Override
    public void partakerSuccess(Integer regimentalId, String orderNo) {
        final SelfOrder selfOrder = selfOrderMapper.selectOne(new LambdaQueryWrapper<SelfOrder>().eq(SelfOrder::getOrderNo, orderNo));
        Optional.ofNullable(selfOrder).orElseThrow(() -> new SelfRuntimeException(ResponseResultUtils.getResponseResultF("订单信息错误")));
        selfOrder.setRegimentalId(regimentalId);
        selfOrder.setStatus(2);
        selfOrder.setUpdateTime(DateUtil.date());
        selfOrder.setSuccessTime(DateUtil.date());
        selfOrder.setRedeem(IdUtil.fastUUID().split("-")[4].toUpperCase());
        selfOrderMapper.updateById(selfOrder);

        final Commodity commodity = commodityMapper.selectOne(new LambdaQueryWrapper<Commodity>().eq(Commodity::getId, selfOrder.getCommodityId()));
        final Subscribers subscribers = subscribersMapper.selectByPrimaryKey(selfOrder.getUserId());
        if (commodity != null && subscribers != null) {
            final Broadcast broadcast = Broadcast
                    .builder()
                    .commodityId(commodity.getId())
                    .commodityName(commodity.getCommodityName())
                    .createTime(DateUtil.date())
                    .gainer(getGainer(subscribers))
                    .status(0)
                    .marketPrice(commodity.getCommodityMarketPrice())
                    .realPrice(selfOrder.getRealPrice().add(selfOrder.getDiscountPrice()))
                    .build();
            broadcastMapper.insert(broadcast);
        }
    }

    @Override
    public void partakerFailing(Integer regimentalId, String orderNo) {
        final SelfOrder selfOrder = selfOrderMapper.selectOne(new LambdaQueryWrapper<SelfOrder>().eq(SelfOrder::getOrderNo, orderNo));
        Optional.ofNullable(selfOrder).orElseThrow(() -> new SelfRuntimeException(ResponseResultUtils.getResponseResultF("订单信息错误")));
        selfOrder.setRegimentalOutId(regimentalId);
        selfOrder.setStatus(5);
        selfOrder.setUpdateTime(DateUtil.date());
        selfOrderMapper.updateById(selfOrder);

        final Ptintegral ptintegral = new Ptintegral();
        ptintegral.setCreateTime(DateUtil.date());
        ptintegral.setContext("拼团失败["+ orderNo + "]所返");
        ptintegral.setMoney(selfOrder.getRealPrice().add(selfOrder.getDiscountPrice()));
        ptintegral.setSub(selfOrder.getUserId());
        ptintegral.setType(1);
        ptintegral.setStatus(1);
        ptintegralMapper.insert(ptintegral);
    }

    @Override
    public String getTotalMoney(Users users) {
        List<SelfOrder> selfOrderList = selfOrderMapper.selectList(new LambdaQueryWrapper<SelfOrder>()
                .select(SelfOrder::getRealPrice, SelfOrder::getDiscountPrice)
                .eq(SelfOrder::getShopId, users.getId())
                .ne(SelfOrder::getStatus, 1)
                .ne(SelfOrder::getStatus, 5)
                .eq(SelfOrder::getCarrierId, 0)
                .eq(SelfOrder::getIsDel, 0)
        );
        BigDecimal totalMoney = selfOrderList
                .stream()
                .map(x -> x.getRealPrice().add(x.getDiscountPrice()))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        return totalMoney
                .divide(
                        new BigDecimal("10000"),
                        4,
                        BigDecimal.ROUND_HALF_DOWN)
                .setScale(
                        2,
                        BigDecimal.ROUND_HALF_DOWN)
                .stripTrailingZeros()
                .toPlainString();
    }

    @Override
    public ResponseResult selfOrderTotalList(SelfOrderTotalListDTO selfOrderTotalListDTO) {
        final Map<String, Object> data = PageUtils.getDateMapBack(() -> page(PageUtils.getPage(
                new Page<>(), selfOrderTotalListDTO.getOffset(), selfOrderTotalListDTO.getLimit()),
                new LambdaQueryWrapper<SelfOrder>()
                        .eq(SelfOrder::getShopId, selfOrderTotalListDTO.getShopId())
                        .eq(SelfOrder::getIsDel, 0)
                        .orderByDesc(SelfOrder::getCreateTime))
                ,
                page -> {
                    List<SelfOrder> data1 = page.getRecords();

                    return data1.stream().map(x -> {
                        final Commodity commodity = commodityMapper.selectById(x.getCommodityId());
                        return new SelfOrderTotalListVO(
                                x.getMobile(),
                                commodity.getCommodityName(),
                                x.getOrderNo(),
                                x.getRealPrice(),
                                x.getDiscountPrice()
                        );
                    });
                }
        );
        return ResponseResultUtils.getResponseResultS("查询成功", data);
    }

    private String getGainer(final Subscribers subscribers){
        if (StringUtils.isEmpty(subscribers.getUsername())) {
            return subscribers.getMobile().replaceAll("(\\d{3})\\d{4}(\\d{4})","$1****$2");
        }
        return subscribers.getUsername().replaceAll("(\\S)\\S{2,}", "$1**");
    }

    private String[] split(String createTime){
        if (org.apache.commons.lang.StringUtils.isNotEmpty(createTime)) {
            if (!createTime.contains(" - ")) {
                throw new SelfRuntimeException(ResponseResultUtils.getResponseResultF("日期范围错误"));
            }
            return createTime.split(" - ");
        }
        return new String[0];
    }

    private String commoditySubarea(Integer status) {
        if (status == 0) {
            return "奖励金区";
        }
        if (status == 1) {
            return "积分区";
        }
        return "";
    }

    private String tradeStatus(Integer status) {
        if (status == 1) {
            return "待支付";
        }
        if (status == 2) {
            return "待发货";
        }
        if (status == 3) {
            return "待收货";
        }
        if (status == 4) {
            return "待晒单";
        }
        if (status == 5) {
            return "已取消";
        }
        return "";
    }

    private String getExpressStatus(Integer status){
        if (status == 0) {
            return "未发货";
        }
        if (status == 1) {
            return "已发货";
        }
        return "";
    }

    private String payWayStatus(Integer status){
        if (status == 1) {
            return "支付宝";
        }
        if (status == 2) {
            return "微信";
        }
        if (status == 3) {
            return "云闪付";
        }
        return "";
    }

    private String isReplacementStatus(Integer status){
        if (status == 0) {
            return "未置换";
        }
        if (status == 1) {
            return "已置换";
        }
        return "";
    }
}
